# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 装饰器
"""

import time
import json
from functools import wraps
from collections import defaultdict, deque
from datetime import datetime, timedelta
from flask import request, jsonify, current_app, g
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt
from app.models import User, AdminUser


# 简单的内存限流器
class RateLimiter:
    def __init__(self):
        self.requests = defaultdict(deque)
    
    def is_allowed(self, key: str, limit: int, window: int) -> bool:
        """检查是否允许请求
        
        Args:
            key: 限流键
            limit: 限制次数
            window: 时间窗口（秒）
        
        Returns:
            是否允许
        """
        now = time.time()
        requests = self.requests[key]
        
        # 清理过期请求
        while requests and requests[0] <= now - window:
            requests.popleft()
        
        # 检查是否超限
        if len(requests) >= limit:
            return False
        
        # 记录当前请求
        requests.append(now)
        return True


# 全局限流器实例
rate_limiter = RateLimiter()


def admin_required(f):
    """管理员权限装饰器"""
    @wraps(f)
    @jwt_required()
    def decorated_function(*args, **kwargs):
        try:
            # 检查JWT类型
            claims = get_jwt()
            if claims.get('user_type') != 'admin':
                return jsonify({
                    'success': False,
                    'message': '需要管理员权限'
                }), 403
            
            # 获取管理员信息
            admin_id_str = get_jwt_identity()
            admin_id = int(admin_id_str)  # 转换为整数
            admin = AdminUser.query.get(admin_id)
            
            if not admin or not admin.is_active:
                return jsonify({
                    'success': False,
                    'message': '管理员账户不存在或已被禁用'
                }), 403
            
            # 将管理员信息存储到g对象
            g.current_admin = admin
            
            return f(*args, **kwargs)
            
        except Exception as e:
            current_app.logger.error(f'管理员权限验证失败: {str(e)}')
            return jsonify({
                'success': False,
                'message': '权限验证失败'
            }), 500
    
    return decorated_function


def member_required(membership_types=None):
    """会员权限装饰器
    
    Args:
        membership_types: 允许的会员类型列表
    """
    if membership_types is None:
        membership_types = ['basic', 'professional', 'institution', 'research']
    
    def decorator(f):
        @wraps(f)
        @jwt_required()
        def decorated_function(*args, **kwargs):
            try:
                # 获取用户信息
                user_id = get_jwt_identity()
                user = User.get_by_id(user_id)
                
                if not user or not user.is_active:
                    return jsonify({
                        'success': False,
                        'message': '用户不存在或已被禁用'
                    }), 403
                
                # 检查会员类型
                membership_type = user.get_membership_type()
                if membership_type not in membership_types:
                    return jsonify({
                        'success': False,
                        'message': f'需要 {"/".join(membership_types)} 会员权限'
                    }), 403
                
                # 将用户信息存储到g对象
                g.current_user = user
                g.membership_type = membership_type
                
                return f(*args, **kwargs)
                
            except Exception as e:
                current_app.logger.error(f'会员权限验证失败: {str(e)}')
                return jsonify({
                    'success': False,
                    'message': '权限验证失败'
                }), 500
        
        return decorated_function
    
    return decorator


def rate_limit(limit: int = 100, window: int = 3600, key_func=None):
    """限流装饰器
    
    Args:
        limit: 限制次数
        window: 时间窗口（秒）
        key_func: 自定义键函数
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 生成限流键
            if key_func:
                key = key_func()
            else:
                # 默认使用IP地址
                from .helpers import get_client_ip
                key = f"rate_limit:{get_client_ip(request)}:{f.__name__}"
            
            # 检查限流
            if not rate_limiter.is_allowed(key, limit, window):
                return jsonify({
                    'success': False,
                    'message': '请求过于频繁，请稍后重试',
                    'retry_after': window
                }), 429
            
            return f(*args, **kwargs)
        
        return decorated_function
    
    return decorator


def validate_json(required_fields=None, optional_fields=None):
    """JSON验证装饰器
    
    Args:
        required_fields: 必填字段列表
        optional_fields: 可选字段列表
    """
    required_fields = required_fields or []
    optional_fields = optional_fields or []
    
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                # 检查Content-Type
                if not request.is_json:
                    return jsonify({
                        'success': False,
                        'message': '请求必须是JSON格式'
                    }), 400
                
                # 获取JSON数据
                data = request.get_json()
                if data is None:
                    return jsonify({
                        'success': False,
                        'message': 'JSON数据格式错误'
                    }), 400
                
                # 验证必填字段
                missing_fields = []
                for field in required_fields:
                    if field not in data or data[field] is None:
                        missing_fields.append(field)
                
                if missing_fields:
                    return jsonify({
                        'success': False,
                        'message': f'缺少必填字段: {", ".join(missing_fields)}'
                    }), 400
                
                # 验证字段类型（如果指定）
                all_fields = {**required_fields, **optional_fields} if isinstance(required_fields, dict) else {}
                if isinstance(all_fields, dict):
                    for field, expected_type in all_fields.items():
                        if field in data and data[field] is not None:
                            if not isinstance(data[field], expected_type):
                                return jsonify({
                                    'success': False,
                                    'message': f'字段 {field} 类型错误，期望 {expected_type.__name__}'
                                }), 400
                
                # 将验证后的数据存储到g对象
                g.json_data = data
                
                return f(*args, **kwargs)
                
            except json.JSONDecodeError:
                return jsonify({
                    'success': False,
                    'message': 'JSON格式错误'
                }), 400
            except Exception as e:
                current_app.logger.error(f'JSON验证失败: {str(e)}')
                return jsonify({
                    'success': False,
                    'message': '请求验证失败'
                }), 500
        
        return decorated_function
    
    return decorator


def log_api_call(f):
    """API调用日志装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        start_time = time.time()
        
        # 记录请求信息
        from .helpers import get_client_ip
        request_info = {
            'method': request.method,
            'url': request.url,
            'ip': get_client_ip(request),
            'user_agent': request.headers.get('User-Agent', ''),
            'timestamp': datetime.utcnow().isoformat()
        }
        
        try:
            # 执行函数
            response = f(*args, **kwargs)
            
            # 计算执行时间
            execution_time = time.time() - start_time
            
            # 记录成功日志
            current_app.logger.info(
                f"API调用成功: {request.method} {request.path} "
                f"- IP: {request_info['ip']} "
                f"- 耗时: {execution_time:.3f}s"
            )
            
            return response
            
        except Exception as e:
            # 计算执行时间
            execution_time = time.time() - start_time
            
            # 记录错误日志
            current_app.logger.error(
                f"API调用失败: {request.method} {request.path} "
                f"- IP: {request_info['ip']} "
                f"- 错误: {str(e)} "
                f"- 耗时: {execution_time:.3f}s"
            )
            
            raise
    
    return decorated_function


def cache_response(timeout=300, key_func=None):
    """响应缓存装饰器
    
    Args:
        timeout: 缓存超时时间（秒）
        key_func: 自定义缓存键函数
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 生成缓存键
            if key_func:
                cache_key = key_func(*args, **kwargs)
            else:
                cache_key = f"cache:{f.__name__}:{hash(str(args) + str(kwargs))}"
            
            # TODO: 实现Redis缓存
            # 这里可以集成Redis缓存逻辑
            
            return f(*args, **kwargs)
        
        return decorated_function
    
    return decorator


def require_permission(permission_name):
    """权限检查装饰器
    
    Args:
        permission_name: 权限名称
    """
    def decorator(f):
        @wraps(f)
        @admin_required
        def decorated_function(*args, **kwargs):
            admin = g.current_admin
            
            # 超级管理员拥有所有权限
            if admin.is_super_admin:
                return f(*args, **kwargs)
            
            # 检查具体权限
            from app.models import AdminPermission
            permission = AdminPermission.query.filter_by(
                admin_id=admin.id,
                permission_name=permission_name
            ).first()
            
            if not permission:
                return jsonify({
                    'success': False,
                    'message': f'缺少权限: {permission_name}'
                }), 403
            
            return f(*args, **kwargs)
        
        return decorated_function
    
    return decorator


def permission_required(permission_code):
    """权限检查装饰器（简化版）
    
    Args:
        permission_code: 权限代码
    """
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            # 从JWT获取管理员信息（因为这个装饰器在admin_required之后调用）
            try:
                admin_id = get_jwt_identity()
                admin = AdminUser.query.get(admin_id)
                
                if not admin:
                    return jsonify({
                        'success': False,
                        'message': '管理员不存在'
                    }), 403
                
                # 超级管理员拥有所有权限
                if admin.is_super_admin:
                    return f(*args, **kwargs)
                
                # 检查具体权限
                has_permission = any(
                    perm.code == permission_code 
                    for perm in admin.permissions
                )
                
                if not has_permission:
                    return jsonify({
                        'success': False,
                        'message': f'缺少权限: {permission_code}'
                    }), 403
                
                return f(*args, **kwargs)
                
            except Exception as e:
                current_app.logger.error(f'权限检查失败: {str(e)}')
                return jsonify({
                    'success': False,
                    'message': '权限验证失败'
                }), 500
        
        return decorated_function
    
    return decorator